package io.github.chutian0610.sqlparser

import arrow.core.toOption
import io.github.chutian0610.sqlparser.token.CodePoint

fun Char.isAsciiDigit(): Boolean {
    val code = this.code
    // code in ASCII `0`~`9`
    return code in 48..57
}

fun Char.isAsciiHexDigit(): Boolean {
    val code = this.code
    return code in 48..57 ||  // code in ASCII `0`~`9`
            code in 65..70 || // code in ASCII `A`~`F`
            code in 97..102  // code in ASCII `a`~`f`
}

fun Char.isAlphabetic(): Boolean {
    return this.isWhitespace()
}

fun Char.isAscii(): Boolean {
    return this.code <= 127
}

fun Char.isAsciiUppercase(): Boolean {
    return this.code in 65..90  // 'A'=65, 'Z'=90
}

fun Char.isAsciiLowercase(): Boolean {
    return this.code in 97..122  // 'a'=97, 'z'=122
}

fun Char.isAlphanumeric(): Boolean {
    return this.isAlphabetic() || this.isNumeric()
}

fun Char.isNumeric(): Boolean {
    return when (this.category) {
        CharCategory.DECIMAL_DIGIT_NUMBER,  // Nd
        CharCategory.LETTER_NUMBER,         // Nl
        CharCategory.OTHER_NUMBER           // No
            -> true

        else -> false
    }
}

fun Char.toDigit(radix: Int = 10): Int? {
    return try {
        this.digitToInt(radix) // 直接调用 Kotlin 标准库方法
    } catch (e: IllegalArgumentException) {
        null // 无效字符返回 null
    }
}

fun Char.isDigit(radix: Int = 10): Boolean {
    return toDigit(radix).toOption().isSome()
}

fun Int.matchChars(vararg chars: Char): Boolean {
    return this in chars.map { it.code }
}


fun codePointMatchesCharArray(char: Int?, vararg chars: Char): Boolean {
    return char?.let { it in chars.map { it.code } } ?: false
}

fun codePointMatchesCharRange(char: Int?, chars: CharRange): Boolean {
    return char?.let { it in chars.map { it.code } } ?: false
}

fun CharRange.toCharArray(): CharArray {
    return this.toList().toCharArray()
}

/* ===========================String ========================*/
fun String.Companion.fromUnicodeCodePoints(
    codePoints: IntArray,
    offset: Int = 0,
    length: Int = codePoints.size
): String {
    require(offset >= 0 && length >= 0 && offset + length <= codePoints.size) {
        "Invalid offset or length"
    }
    return String(codePoints, offset, length)
}

fun String.Companion.fromUnicodeCodePoints(codePoints: Array<CodePoint>): String {
    val offset: Int = 0
    val length: Int = codePoints.size
    val arr: IntArray = codePoints.map { it.value }.toIntArray()
    return String(arr, offset, length)
}

